﻿using System;
using System.Collections.Generic;

namespace SS.Common.Utilities
{
    /// <summary>
    /// Helper class for working with 'extended' enums using <see cref="StringValueAttribute"/> attributes.
    /// </summary>
    public class StringEnum<T>
    {
        private static readonly IDictionary<T, StringValueAttribute> _stringValues =
            new Dictionary<T, StringValueAttribute>();

        /// <summary>
        /// Gets a string value for a particular enum value.
        /// </summary>
        /// <param name="value">Value.</param>
        /// <returns>String Value associated via a <see cref="StringValueAttribute"/> attribute, or null if not found.</returns>
        public static string GetStringValue(T value)
        {
            string output = null;

            if (_stringValues.ContainsKey(value))
            {
                var stringValueAttribute = _stringValues[value];
                if (stringValueAttribute != null)
                {
                    output = stringValueAttribute.Value;
                }
            }

            return output;

        }

        /// <summary>
        /// Look for our 'StringValueAttribute' in the field's custom attributes
        /// </summary>
        /// <param name="enumValues"></param>
        public static void InitStringValues(IEnumerable<T> enumValues)
        {
            foreach (var enumValue in enumValues)
            {
                var type = enumValue.GetType();
                var fi = type.GetField(enumValue.ToString());
                var attrs = fi.GetCustomAttributes(typeof(StringValueAttribute), false) as StringValueAttribute[];
                if (attrs != null && attrs.Length > 0)
                {
                    _stringValues.Add(enumValue, attrs[0]);
                }
            }
        }
    }

    /// <summary>
    /// Simple attribute class for storing String Values
    /// </summary>
    public class StringValueAttribute : Attribute
    {
        private readonly string _value;

        /// <summary>
        /// Creates a new <see cref="StringValueAttribute"/> instance.
        /// </summary>
        /// <param name="value">Value.</param>
        public StringValueAttribute(string value)
        {
            _value = value;
        }

        /// <summary>
        /// Gets the value.
        /// </summary>
        /// <value></value>
        public string Value
        {
            get { return _value; }
        }
    }
}